<?php
/**
 * libICase
 * Access Control Library
 * Includes user register,group management,access control,link to UCenter/weibo etc. function
 * @author Pony
 * @link http://icase-speedphp.googlecode.com
 * @link http://www.speedphp.com
 * @version 2.0-plus-2011.08.19
 *
 */

class libICase{
	
	private $REGISTER_GROUP = NULL;//新用户注册默认组ID，若为NULL，则从spAccess中读取
	
	function __construct(){
		if($this->REGISTER_GROUP === NULL) $this -> REGISTER_GROUP = spAccess('r','ICASE_REGISTER_GROUP');
	}
	
	function acl_group_get($groups_id = NULL){
		return spClass('modICase') -> m_group_get($groups_id);
	}
	
	function acl_group_add($groups_name,$groups_type = 'min'){
		if(empty($groups_name)) return '-1';//组名称未填
		$result = spClass('modICase') -> m_group_add($groups_name,$groups_type);
		if(!$result) return '-2';//其它原因导致未新增成功
		else return $result;//成功
	}
	
	function acl_group_edit($groups_id,$groups_name = NULL,$groups_type = NULL){
		if(empty($groups_id)) return '-1';//组ID未填
		elseif($groups_name !== NULL && empty($groups_name)) return '-2';//组名称不可为空
		elseif($groups_type !== NULL && empty($groups_type)) return '-3';//组权限不可为空，为min或max
		$result = spClass('modICase') -> m_group_edit($groups_id,$groups_name,$groups_type);
		if(!$result) return '0';//未知原因导致编辑失败
		else return '1';//成功
	}
	
	function acl_group_delete($groups_id){
		if(empty($groups_id)) return '-1';//组ID未填
		$result = spClass('modICase') -> m_group_delete($groups_id);
		if(!$result) return '0';//未知原因导致编辑失败
		else return '1';//成功
	}
	
	function acl_user_get($users_id = NULL,$users_username = NULL,$users_email = NULL,$page_no = 1){
		return spClass('modICase') -> m_user_get($users_id,$users_username,$users_email,$page_no);
	}
	
	function acl_user_add($users_username = NULL,$users_password = NULL,$users_salt = NULL,$users_email = NULL,$users_groups_id = NULL){
		if(empty($users_username)) return '-1';//用户名不可为空
		elseif(empty($users_password)) return '-2';//密码不可为空
		elseif(empty($users_email)) return '-3';//邮箱不可为空
		elseif(empty($users_groups_id)) return '-9';//组ID不可为空
		elseif(empty($users_salt)) return '-8';//骚扰码不可为空
		return spClass('modICase') -> m_user_add($users_username,$users_password,$users_salt,$users_email,$users_groups_id);//成功则返回用户ID 
	}
	
	function acl_user_edit($users_id,$users_username = NULL,$users_password = NULL,$users_email = NULL,$users_groups_id = NULL){
		if(empty($users_id)) return '-1';//用户ID不可为空
		if(!empty($users_password)){
			$users_salt = substr(md5(mt_rand(0, 100000000)),0,16);
			$password_encode = md5($users_password.$users_salt);
		}
		else{
			$password_encode = NULL;$users_salt = NULL;
		}
		$result = spClass('modICase') -> m_user_edit($users_id,$users_username,$password_encode,$users_salt,$users_email,$users_groups_id);
		if(!$result) return '0';//编辑更改，信息没有变更
		else return '1';
	}
	
	function acl_user_register($username,$password,$email){
		if(empty($username)) return '-1';//用户名不可为空
		elseif(empty($password)) return '-2';//密码不可为空
		elseif(empty($email)) return '-3';//邮箱不可为空
		elseif(preg_match('/[^\w]/', $username) > 0) return '-4';//用户名非法
		elseif(preg_match('/^[\w\-\.]+@[\w\-]+(\.\w+)+$/', $email) == 0) return '-5';//邮箱非法
		$salt = substr(md5(mt_rand(0, 100000000)),0,16);
		$password_encode = md5($password.$salt);
		return $this -> acl_user_add($username,$password_encode,$salt,$email,$this -> REGISTER_GROUP);//大于0成功，-6用户名冲突-7邮箱冲突
	}
	
	function acl_user_login($username_email,$password){
		if(strpos($username_email,'@') > 0) $userInfo = spClass('modICase') -> m_user_get(NULL,NULL,$username_email);
		else $userInfo = spClass('modICase') -> m_user_get(NULL,$username_email);
		if(empty($userInfo)) return '-1';//找不到该用户
		$password_encode = md5($password.$userInfo[0]['salt']);
		if($userInfo[0]['password'] != $password_encode) return '-2';//密码错误
		else return $userInfo[0];
	}
	
	function acl_user_reset($username,$email){
		//初步考虑使用邮箱链接方式验证身份，然后重置密码
	}
	
	function acl_user_password($users_name,$oldpassword,$newpassword){
		$check = $this -> acl_user_login($users_name, $oldpassword);
		if($check <= 0) return '-1';//旧密码验证不通过
		else return $this -> acl_user_edit($check['id'],NULL,$newpassword);
	}
	
	function acl_rule_get($rules_id = NULL,$rules_groups_id = NULL,$rules_controller = NULL,$rules_action = NULL,$rules_code = NULL,$rules_allow = NULL){
		return spClass('modICase') -> m_rule_get($rules_id,$rules_groups_id,$rules_controller,$rules_action,$rules_code,$rules_allow);
	}
	
	function acl_rule_add($rules_groups_id = NULL,$rules_controller = NULL,$rules_action = NULL,$rules_code = NULL,$rules_allow = NULL,$rules_start = NULL,$rules_end = NULL,$rules_note = NULL){
		if(empty($controller) && empty($action) && empty($rules_code)) return '-1';//控制器、动作、代码不可全为空
		elseif(empty($rules_allow)) return '-2';//必须为1或0
		$result = spClass('modICase') -> m_rule_add($rules_groups_id,$rules_controller,$rules_action,$rules_code,$rules_allow,$rules_start,$rules_end,$rules_note);
		if(!$result) return '0';//新增失败，未知原因
		else return $result;//返回条目ID
	}
	
	function acl_rule_edit($rules_id,$rules_groups_id = NULL,$rules_controller = NULL,$rules_action = NULL,$rules_code = NULL,$rules_allow = NULL,$rules_start = NULL,$rules_end = NULL,$rules_note = NULL){
		if(empty($rules_id)) return '-1';//条目ID不可为空
		else return spClass('modICase') -> m_rule_edit($rules_id,$rules_groups_id,$rules_controller,$rules_action,$rules_code,$rules_allow,$rules_start,$rules_end,$rules_note);//成功返回真值
	}
	
	function acl_rule_delete($rules_id){
		if(empty($rules_id)) return '-1';//条目ID不可为空
		else return spClass('modICase') -> m_rule_delete($rules_id);
	}
	
	function acl_rule_verify($users_id,$rules_controller = NULL,$rules_action = NULL,$rules_code = NULL){
		if(empty($users_id)) return '-1';//用户ID不可为空
		if(empty($rules_controller) && empty($rules_action) && empty($rules_code)) return '-2';//条件不可全为空
		$userInfo = $this -> acl_user_get($users_id);
		//先获识其组别是最大权限OR最小权限
		$groupInfo = $this -> acl_group_get($userInfo[0]['groups_id']);
		$type = $groupInfo[0]['type'];$allow = ($type == 'max') ? TRUE : FALSE;
		$t = time();
		//先检查是否存在全局权限限制
		$G = $this -> acl_rule_get(NULL,'0',$rules_controller,$rules_action,$rules_code);
		if(!empty($G)){
			if($type == 'max'){
				//除非全部条件均为禁止通过，否则将允许通过
				for($i=0;isset($G[$i]);$i++){
					if($G[$i]['allow'] == 0 && (($G[$i]['start'] < $t && $G[$i]['end'] > $t) || ($G[$i]['start'] == 0 && $G[$i]['end'] == 0) || ($G[$i]['start'] < $t && $G[$i]['end'] == 0) || ($G[$i]['start'] == 0 && $G[$i]['end'] > $t) )){
						$allow = FALSE;
					}
					elseif($G[$i]['allow'] == 1 && (($G[$i]['start'] > $t)||($G[$i]['end'] < $t && $G[$i]['end'] != 0))){
						$allow = FALSE;
					}
					else{
						$allow = TRUE;
					}
				}
			}
			elseif($type == 'min'){
				//除非全部条件均为允许通过，否则将禁止通过
				for($i=0;isset($G[$i]);$i++){
					if($G[$i]['allow'] == 1 && (($G[$i]['start'] < $t && $G[$i]['end'] > $t) || ($G[$i]['start'] == 0 && $G[$i]['end'] > $t) || ($G[$i]['end'] == 0 && $G[$i]['start'] < $t) || ($G[$i]['start'] == 0 && $G[$i]['end'] == 0))){
						$allow = TRUE;
					}
					elseif($G[$i]['allow'] == 0 && (($G[$i]['start'] > $t) || ($G[$i]['end'] < $t && $G[$i]['end'] != 0))){
						$allow = TRUE;
					}
					else{
						$allow = FALSE;
					}
				}
			}
		}
		//再检查是否存在组别权限
		$L = $this -> acl_rule_get(NULL,$userInfo[0]['groups_id'],$rules_controller,$rules_action,$rules_code);
		if(!empty($L)){
			if($type == 'max'){
				//除非全部条件均为禁止通过，否则将允许通过
				for($i=0;isset($G[$i]);$i++){
					if($L[$i]['allow'] == 0 && (($L[$i]['start'] < $t && $L[$i]['end'] > $t) || ($L[$i]['start'] == 0 && $L[$i]['end'] == 0) || ($L[$i]['start'] < $t && $L[$i]['end'] == 0) || ($L[$i]['start'] == 0 && $L[$i]['end'] > $t) )){
						$allow = FALSE;
					}
					elseif($L[$i]['allow'] == 1 && (($L[$i]['start'] > $t)||($L[$i]['end'] < $t && $L[$i]['end'] != 0))){
						$allow = FALSE;
					}
					else{
						$allow = TRUE;
					}
				}
			}
			elseif($type == 'min'){
				//除非全部条件均为允许通过，否则将禁止通过
				for($i=0;isset($L[$i]);$i++){
					if($L[$i]['allow'] == 1 && (($L[$i]['start'] < $t && $L[$i]['end'] > $t) || ($L[$i]['start'] == 0 && $L[$i]['end'] > $t) || ($L[$i]['end'] == 0 && $L[$i]['start'] < $t) || ($G[$i]['start'] == 0 && $L[$i]['end'] == 0))){
						$allow = TRUE;
					}
					elseif($L[$i]['allow'] == 0 && (($L[$i]['start'] > $t) || ($L[$i]['end'] < $t && $L[$i]['end'] != 0))){
						$allow = TRUE;
					}
					else{
						$allow = FALSE;
					}
				}
			}
		}
		if(!$allow) return FALSE;
		else return TRUE;
	}
	
	//以下是增强版的内容
	function acl_connect_get($connects_id = NULL,$connects_website = NULL,$connects_webuser = NULL,$connects_users_id = NULL){
		return spClass('modICase') -> m_connect_get($connects_id,$connects_website,$connects_webuser,$connects_users_id);
	}
	
	function acl_connect_add($connects_website,$connects_webuser,$connects_users_id){
		return spClass('modICase') -> m_connect_add($connects_website,$connects_webuser,$connects_users_id);
	}
	
	function acl_connect_delete($connects_id){
		return spClass('modICase') -> m_connect_del($connects_id);
	}
	
	/**
	 * 外部网站提供信息后，给予登录放行信息
	 * 无条件通行，应在执行此方法前，对外部网站提供的签名信息进行验证
	 * 1.先检查是否存在已联接用户
	 * 2.否；若当前已登录，则绑定当前已登录用户
	 * 3.否；再通过外部网站提供的email检查帐户，若不存在已有数据，则生成新帐户
	 * 4.返回ICase用户ID
	 * @param 外部网站标识 $connects_website
	 * @param 外部网站用户标识 $connects_webuser
	 * @param 外部网站用户名 $webusername
	 * @param 当前登录用户ID $current_users_id
	 * @param 外部网站提供的email $webmail
	 */
	function acl_connect_login($connects_website,$connects_webuser,$webusername,$current_users_id,$webmail){
		$firsttry = $this -> acl_connect_get(NULL,$connects_website,$connects_webuser,NULL);
		if($firsttry[0]['users_id'] > 0){
			return $firsttry[0]['users_id'];
		}
		else{
			if($current_users_id > 0){
				$this -> acl_connect_add($connects_website, $connects_webuser, $current_users_id);
				return $current_users_id;
			}
			elseif(!empty($webmail)){
				$result = $this -> acl_user_register($webusername, md5(mt_rand(0, 10000)), $webmail);
				if($result>0){$this->acl_connect_add($connects_website, $connects_webuser, $result);}
				return $result;//返回信息同acl_user_register，若无法注册、冲突，则需先行在本系统注册并登录
			}
			else{
				return '-11';//需要提供EMAIL地址以便继续注册
			}
		}
	}
}

/**
 * modICase
 * All returnings are number/bool
 * @author Pony
 * @version 2011.08.11
 */
class modICase extends spModel{
	/**
	 * ACL数据表前缀
	 * @var string
	 */
	private $PREFIX = NULL;//此参数可修改
	
	function __construct(){
		if($this->PREFIX === NULL) $this->PREFIX = spAccess('r','ICASE_PREFIX');
		parent::__construct();
	}
	
	/**
	 * m_group_get
	 * 从数据库中获取组信息
	 * @param string/组ID $groups_id
	 */
	function m_group_get($groups_id = NULL){
		$this -> tbl_name = $this->PREFIX.'_acl_groups';
		$this -> pk = 'id';
		return empty($groups_id) ? $this->findAll() : $this -> findAll(array('id'=>$groups_id));
	}
	
	/**
	 * m_group_add
	 * 新增一个组
	 * @param string/组名称 $groups_name
	 * @param string/组权限 $groups_type
	 */
	function m_group_add($groups_name,$groups_type = 'min'){
		if(empty($groups_name)) return FALSE;
		$this -> tbl_name = $this->PREFIX.'_acl_groups';
		$this -> pk = 'id';
		return $this -> create(array('name'=>$groups_name,'type'=>$groups_type));
	}
	
	/**
	 * m_group_edit
	 * 编辑一个组
	 * @param string/组ID $groups_id
	 * @param string/组名称 $groups_name
	 * @param string/组权限 $groups_type
	 */
	function m_group_edit($groups_id,$groups_name = NULL,$groups_type = NULL){
		if(empty($groups_id)) return FALSE;
		$this -> tbl_name = $this->PREFIX.'_acl_groups';
		$this -> pk = 'id';
		$row = array('name'=>$groups_name,'type'=>$groups_type);
		$row = $this -> trim($row);
		return $this -> update(array('id'=>$groups_id), $row);
	}
	
	/**
	 * m_group_del
	 * 删除一个组
	 * @param string/组ID $groups_id
	 */
	function m_group_delete($groups_id){
		if(empty($groups_id)) return FALSE;
		$this -> tbl_name = $this->PREFIX.'_acl_groups';
		$this -> pk = 'id';
		return $this -> deleteByPk($groups_id);
	}
	
	/**
	 * m_user_get
	 * 获取用户信息集
	 * 通过任一条件均可筛选得某一用户
	 * @param int/用户ID $users_id
	 * @param string/用户名 $users_username
	 * @param string/用户邮箱 $users_email
	 */
	function m_user_get($users_id = NULL,$users_username = NULL,$users_email = NULL,$page_no = 1){
		$this -> tbl_name = $this->PREFIX.'_acl_users';
		$this -> pk = 'id';
		$conditions = array('id'=>$users_id,'username'=>$users_username,'email'=>$users_email);
		$conditions = $this -> trim($conditions);
		return $this -> findAll($conditions,null,null,(($page_no-1)*30).',30');
	}
	
	/**
	 * m_user_add
	 * 新增一个用户
	 * ！所有的值均不可以为空！
	 * @param string/用户名 $users_username
	 * @param string/加密密文 $users_password
	 * @param string/扰乱码 $users_salt
	 * @param string/用户邮箱 $users_email
	 * @param int/所属组 $users_groups_id
	 */
	function m_user_add($users_username = NULL,$users_password = NULL,$users_salt = NULL,$users_email = NULL,$users_groups_id = NULL){
		$this -> tbl_name = $this->PREFIX.'_acl_users';
		$this -> pk = 'id';
		if($this -> findCount(array('username'=>$users_username)) > 0) return '-6';//数据库中已经有相同的用户名
		elseif($this -> findCount(array('email'=>$users_email)) > 0) return '-7';//数据库中已经有相同的邮箱
		$row = array('username'=>$users_username,'password'=>$users_password,'salt'=>$users_salt,'email'=>$users_email,'groups_id'=>$users_groups_id);
		$row = $this -> trim($row);
		if(count($row) <5) return FALSE;
		return $this -> create($row);
	}
	
	/**
	 * m_user_edit
	 * 修改一个用户的信息
	 * 为NULL的值即不修改
	 * @param int/用户ID $users_id
	 * @param string/用户名 $users_username
	 * @param string/加密密文 $users_password
	 * @param string/扰乱码 $users_salt
	 * @param string/用户邮箱 $users_email
	 * @param int/所属组 $users_groups_id
	 */
	function m_user_edit($users_id,$users_username = NULL,$users_password = NULL,$users_salt = NULL,$users_email = NULL,$users_groups_id = NULL){
		if(empty($users_id)) return FALSE;
		$this -> tbl_name = $this->PREFIX.'_acl_users';
		$this -> pk = 'id';
		$row = array('username'=>$users_username,'password'=>$users_password,'salt'=>$users_salt,'email'=>$users_email,'groups_id'=>$users_groups_id);
		$row = $this -> trim($row);
		return $this -> update(array('id'=>$users_id), $row);
	}
	
	/**
	 * m_user_delete
	 * 删除一个用户,一般来说,此功能不提供直接的接口使用
	 * @param int/用户ID $users_id
	 */
	function m_user_delete($users_id){
		if(empty($users_id)) return FALSE;
		$this -> tbl_name = $this->PREFIX.'_acl_users';
		$this -> pk = 'id';
		return $this -> delete(array('id'=>$users_id));
	}
	
	/**
	 * m_rule_get
	 * 获取权限条目列表
	 * 指定任一或几个条件筛选，其关系为“AND”
	 * @param int/条目ID $rules_id
	 * @param int/组别ID $rules_groups_id
	 * @param string/限制的控制器 $rules_controller
	 * @param string/限制的页面 $rules_action
	 * @param string/设限代码 $rules_code
	 * @param int/允许或阻止 $rules_allow
	 */
	function m_rule_get($rules_id = NULL,$rules_groups_id = NULL,$rules_controller = NULL,$rules_action = NULL,$rules_code = NULL,$rules_allow = NULL){
		$this -> tbl_name = $this->PREFIX.'_acl_rules';
		$this -> pk = 'id';
		$conditions = array('id'=>$rules_id,'groups_id'=>$rules_groups_id,'controller'=>$rules_controller,'action'=>$rules_action,'code'=>$rules_code,'allow'=>$rules_allow);
		$conditions = $this -> trim($conditions);
		return $this -> findAll($conditions);
	}
	
	/**
	 * m_rule_add
	 * 新增一条权限条目
	 * @param int/组别ID $rules_groups_id
	 * @param string/限制的控制器 $rules_controller
	 * @param string/限制的页面 $rules_action
	 * @param string/设限代码 $rules_code
	 * @param int/允许或阻止 $rules_allow
	 * @param int/权限起始时间截 $rules_start
	 * @param int/权限终止时间截 $rules_end
	 * @param string/备注 $rules_note
	 */
	function m_rule_add($rules_groups_id = NULL,$rules_controller = NULL,$rules_action = NULL,$rules_code = NULL,$rules_allow = NULL,$rules_start = NULL,$rules_end = NULL,$rules_note = NULL){
		$this -> tbl_name = $this->PREFIX.'_acl_rules';
		$this -> pk = 'id';
		$row = array('groups_id'=>$rules_groups_id,'controller'=>$rules_controller,'action'=>$rules_action,'code'=>$rules_code,'allow'=>$rules_allow,'start'=>$rules_start,'end'=>$rules_end,'note'=>$rules_note);
		return $this -> create($row);
	}
	
	/**
	 * m_rule_edit
	 * 编辑一条权限条目
	 * @param int/条目ID $rules_id
	 * @param int/组别ID $rules_groups_id
	 * @param string/限制的控制器 $rules_controller
	 * @param string/限制的页面 $rules_action
	 * @param string/设限代码 $rules_code
	 * @param int/允许或阻止 $rules_allow
	 * @param int/权限起始时间截 $rules_start
	 * @param int/权限终止时间截 $rules_end
	 * @param string/备注 $rules_note
	 */
	function m_rule_edit($rules_id,$rules_groups_id = NULL,$rules_controller = NULL,$rules_action = NULL,$rules_code = NULL,$rules_allow = NULL,$rules_start = NULL,$rules_end = NULL,$rules_note = NULL){
		if(empty($rules_id)) return '-1';//权限ID不可为空
		$this -> tbl_name = $this->PREFIX.'_acl_rules';
		$this -> pk = 'id';
		$conditions = array('id'=>$rules_id);
		$row = array('groups_id'=>$rules_groups_id,'controller'=>$rules_controller,'action'=>$rules_action,'code'=>$rules_code,'allow'=>$rules_allow,'start'=>$rules_start,'end'=>$rules_end,'note'=>$rules_note);
		$row = $this -> trim($row);
		return $this -> update($conditions, $row);
	}
	
	/**
	 * 删除一条权限条目
	 * @param int/条目ID $rules_id
	 */
	function m_rule_delete($rules_id){
		if(empty($rules_id)) return '-1';//权限ID不可为空
		$this -> tbl_name = $this->PREFIX.'_acl_rules';
		$this -> pk = 'id';
		return $this -> delete(array('id'=>$rules_id));
	}
	
	/**
	 * 获取联接列表
	 * 可根据条件组合筛选
	 * @param 联接ID $connects_id
	 * @param 网站标识 $connects_website
	 * @param 外部网站用户标识 $connects_webuser
	 * @param ICase用户ID $connects_users_id
	 */
	function m_connect_get($connects_id = NULL,$connects_website = NULL,$connects_webuser = NULL,$connects_users_id = NULL){
		$conditions = array('id'=>$connects_id,'website'=>$connects_website,'webuser'=>$connects_webuser,'users_id'=>$connects_users_id);
		$conditions = $this -> trim($conditions);
		$this -> tbl_name = $this -> PREFIX.'_acl_connects';
		$this -> pk = 'id';
		return $this -> findAll($conditions);
	}
	
	/**
	 * 新增一个外部网站联接用户
	 * @param 网站标识 $connects_website
	 * @param 外部网站用户标识 $connects_webuser
	 * @param ICase用户ID $connects_users_id
	 */
	function m_connect_add($connects_website,$connects_webuser,$connects_users_id){
		if(empty($connects_website)) return '-1';//网站标识不可为空
		if(empty($connects_webuser)) return '-2';//外部网站用户标识不可为空
		if(empty($connects_users_id)) return '-3';//ICase对应用户ID不可为空
		$this -> tbl_name = $this -> PREFIX.'_acl_connects';
		$this -> pk = 'id';
		return $this -> create(array('website'=>$connects_website,'webuser'=>$connects_webuser,'users_id'=>$connects_users_id));
	}
	
	/**
	 * 删除一个外部网站联接
	 * @param 联接ID $connects_id
	 */
	function m_connect_delete($connects_id){
		if(empty($connects_id)) return '-1';//联接ID不可为空
		$this -> tbl_name = $this -> PREFIX.'_acl_connects';
		$this -> pk = 'id';
		return $this -> deleteByPk($connects_id);
	}
	
	/**
	 * trim
	 * 将无值的ROW数组元素删去
	 * 值为NULL即不更新
	 * @param array $array
	 */
	function trim($array){
		foreach ($array as $k => $v){
			if($v === NULL) unset($array[$k]);
		}
		return $array;
	}
}